package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.WemediaConstants;
import com.heima.common.constants.WmNewsMessageConstants;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.common.ThreadLocalUtil;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.service.WmMaterialService;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsMaterialService;
import com.heima.wemedia.service.WmNewsService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author itheima
 */
@Slf4j
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private WmMaterialService wmMaterialService;

    @Autowired
    private WmNewsAuditService wmNewsAuditService;

    /**
     * 发布文章
     * @param dto
     * @param isSubmit
     * @return
     */
    @GlobalTransactional
    @Override
    public ResponseResult submit(WmNewsDto dto, Integer isSubmit) {
        //1.判断参数是否为空，是否合法
        if (dto.getTitle() == null || dto.getContent() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2.创建文章还是更新文章
        //2.1将dto拷贝给pojo
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews);
        //2.2处理images属性的值（dto和pojo类型不一样的）
        List<String> coverImageList = dto.getImages();
        if (coverImageList != null && coverImageList.size() > 0){
            String coverImageStr = StringUtils.join(coverImageList, ",");
            wmNews.setImages(coverImageStr);
        }
        //2.3判断是自动布局则设置自动布局为空（后面业务还会决定最终布局）
        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            dto.setType(null);
        }
        //2.4根据id判断是创建还是更新文章
        ResponseResult responseResult = this.saveOrUpdateWmNews(dto, isSubmit, wmNews);
        if (responseResult != null){
            return responseResult;
        }
        //提取内容中所有的封面图片和地址列表
        List<String> contentImageList = extractContentImageList(dto);
        //3.如果提交审核-保存内容图片和文章关系
        if (isSubmit.equals(WmNews.Status.SUBMIT.getCode()) && contentImageList.size() > 0){
            responseResult = this.saveRelation(wmNews.getId(), contentImageList, WemediaConstants.WM_CONTENT_REFERENCE);
            if (responseResult != null){
                return responseResult;
            }
        }
        //4.如果提交审核-保存封面图片和文章关系
        if (isSubmit.equals(WmNews.Status.SUBMIT.getCode())){
            responseResult = saveCoverImageRelation(dto, wmNews, contentImageList);
            if (responseResult != null) {
                return responseResult;
            }

            //调用文章自动审核
            wmNewsAuditService.auditWmNews(wmNews,contentImageList);

        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 抽取：自媒体文章分页列表查询
     * @param dto
     * @return
     */
    @Override
    public ResponseResult list(WmNewsPageReqDto dto) {
        //1.分页参数默认数据
        dto.checkParam();
        //2.多条件查询
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WmNews::getUserId,ThreadLocalUtil.getUserId());
        //动态条件查询1；根据状态查询
        if(dto.getStatus()!=null){
            wrapper.eq(WmNews::getStatus,dto.getStatus());
        }
        //动态条件查询2：根据标题模糊查询
        if(StringUtils.isNotBlank(dto.getKeyword())){
            wrapper.like(WmNews::getTitle,dto.getKeyword());
        }
        //动态条件查询3：根据频道查询
        if (dto.getChannelId()!=null){
            wrapper.eq(WmNews::getChannelId,dto.getChannelId());
        }
        //动态条件查询4：根据发布时间范围查询
        if (dto.getBeginPubDate()!=null && dto.getEndPubDate() !=null){
            wrapper.between(WmNews::getPublishTime,dto.getBeginPubDate(),dto.getEndPubDate());
        }
        wrapper.orderByDesc(WmNews::getCreatedTime);
        //3,page固定条件
        IPage<WmNews> page = new Page<>(dto.getPage(),dto.getSize());
        this.page(page,wrapper);
        //4.封装分页响应结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(),dto.getSize(),page.getTotal());
        responseResult.setData(page.getRecords());
        return responseResult;
    }


    @Autowired
    private KafkaTemplate kafkaTemplate;
    /**
     * 文章上下架
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        //1.判断文章是否存在
        WmNews wmNews = new WmNews();
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"自媒体文章不存在");
        }
        //2.判断是否发布
        if (!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"文章未发布无法正常上下架");
        }
        //3.更新enable值
        WmNews wmNewsDB = new WmNews();
        wmNewsDB.setId(dto.getId());
        wmNewsDB.setEnable(dto.getEnable());
        this.updateById(wmNewsDB);

        Map map = new HashMap();
        map.put("articleId", wmNews.getArticleId());//APP文章ID
        map.put("enable", dto.getEnable());//自媒体文章上下架状态
        //4.生成消息到kafka
        kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(map));
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 抽取：保存封面图片和文章关系
     * @param dto
     * @param wmNews
     * @param contentImageList
     * @return
     */
    private ResponseResult saveCoverImageRelation(WmNewsDto dto, WmNews wmNews, List<String> contentImageList) {
        ResponseResult responseResult;
        //获取封面图片列表
        List<String> coverImageUrlList = dto.getImages();

        //判断是否是自动布局
        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){
            int contentImageSize = contentImageList.size();
            //自动匹配规则1：如果内容图片数量大于等于3，则取前三张图片为封面图片，设置最终布局为多图布局
            if (contentImageSize >= 3){
                coverImageUrlList = contentImageList.stream().limit(3).collect(Collectors.toList());
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
            }else if (contentImageSize >=1 ){
                //自动匹配规则1：如果内容图片数量大于等于1，则取前一张图片为封面图片，设置最终布局为单图布局
                coverImageUrlList = contentImageList.stream().limit(1).collect(Collectors.toList());
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
            }else{
                //自动匹配规则1：如果内容图片数量为0，设置最终布局为无图布局
                coverImageUrlList = new ArrayList<>();
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }
            if(coverImageUrlList.size()>0){
                String coverImageStr = StringUtils.join(contentImageList, ",");
                wmNews.setImages(coverImageStr);
            }
            //更新文章
            this.updateById(wmNews);
        }

        //列表有值就建立数据关系
        if (coverImageUrlList != null && coverImageUrlList.size() > 0){
            responseResult = this.saveRelation(wmNews.getId(), coverImageUrlList, WemediaConstants.WM_COVER_REFERENCE);
            if (responseResult != null){
                return responseResult;
            }
        }
        return null;
    }

    /**
     * 抽取：提取内容中所有的封面图片和地址列表
     * @param dto
     * @return
     */
    private List<String> extractContentImageList(WmNewsDto dto) {
        List<String> contentImageList = new ArrayList<>();
        String content = dto.getContent();
        if (StringUtils.isNotBlank(content)){
            List<Map> mapList = JSON.parseArray(content, Map.class);
            if (mapList!= null && mapList.size()>0){
                for (Map<String,String> map : mapList) {
                    String type = map.get("type");
                    if ("image".equals(type)){
                        String imageUrl = map.get("value");
                        contentImageList.add(imageUrl);
                    }
                }
            }
        }
        return contentImageList;
    }

    /**
     * 抽取：根据id创建和保存文章
     * @param dto
     * @param isSubmit
     * @param wmNews
     * @return
     */
    private ResponseResult saveOrUpdateWmNews(WmNewsDto dto, Integer isSubmit, WmNews wmNews) {
        wmNews.setUserId(ThreadLocalUtil.getUserId());
        wmNews.setStatus(isSubmit);
        wmNews.setSubmitedTime(new Date());
        wmNews.setEnable(WemediaConstants.ENABLE_UP);
        if (dto.getId() == null){
            wmNews.setCreatedTime(new Date());
            this.save(wmNews);
        }else{
            //判断文章是否存在
            WmNews wmNewsDB = this.getById(dto.getId());
            if (wmNewsDB == null){
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "自媒体文章不存在");
            }
            //更新文章
            this.updateById(wmNews);
            //删除关联关系
            wmNewsMaterialService.remove(Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId, dto.getId()));
        }
        return null;
    }

    /**
     * 公共方法 保存素材与文章的关系
     * @param wmNewsId 自媒体文章id
     * @param imageUrlList 素材地址列表
     * @param type 引用类型  0-内容引用 1-主图引用
     * @return
     */
    private ResponseResult saveRelation(Integer wmNewsId, List<String> imageUrlList, int type){
        //根据图片的地址查询到对应的素材列表 select id from wm_material int where url in(?,?,?)
        List<WmMaterial> wmMaterialList = wmMaterialService.list(Wrappers.<WmMaterial>lambdaQuery()
                .in(WmMaterial::getUrl, imageUrlList).select(WmMaterial::getId));
        //判断是否查询到所有数据
        if (wmMaterialList.size() == imageUrlList.size()){
            return ResponseResult.errorResult(AppHttpCodeEnum.MATERIASL_REFERENCE_FAIL);
        }
        //获取到所有的素材id得到素材id列表
        List<Integer> materialIdList = wmMaterialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        //遍历素材id列表逐一去构建关系数据
        int ord = 0;
        List<WmNewsMaterial> wmNewsMaterialList = new ArrayList<>();
        for (Integer materialId : materialIdList) {
            WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
            wmNewsMaterial.setNewsId(wmNewsId );
            wmNewsMaterial.setMaterialId(materialId);
            wmNewsMaterial.setType(type);
            wmNewsMaterial.setOrd(ord);
            ord++;
            wmNewsMaterialList.add(wmNewsMaterial);
        }
        //批量把数据保存到表中 insert into wm_nwe_material values(?,?,?),(?,?,?),(?,?,?)
        wmNewsMaterialService.saveBatch(wmNewsMaterialList);
        return null;
    }
}
